package com.beverages.files.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.beverages.files.common.Constants;
import com.beverages.files.mapper.FilesMapper;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.beverages.files.entity.Files;
import com.beverages.files.service.IFilesService;
import com.beverages.files.common.Result;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;

@RestController
@RequestMapping("/shared/files")
public class FilesController {
    @Value("${files.upload.path}")
    private String fileUploadPath;

    @Value("${server.ip}")
    private String serverIp;

    @Value("${server.port}")
    private String serverPort;

    @Resource
    private IFilesService filesService;

    @Resource
    private FilesMapper filesMapper;

    @ApiOperation(
            value = "列出文件",
            response = Result.class,
            tags = {"这些接口不用管"}
    )
    @GetMapping("/page")
    public Result findPage(@RequestParam Integer pageNum,
                           @RequestParam Integer pageSize) {
        IPage<Files> page = new Page<>(pageNum, pageSize);
        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();

        return Result.success(filesService.page(page, queryWrapper));
    }

    @ApiOperation(
            value = "上传文件",
            notes = "该接口可上传任何小于100MB的文件，需要在移动端判断上传文件的类型，只能是PNG或JPEG。\n",
            response = Integer.class,
            tags = {"上传文件"}
    )
    @PostMapping("/upload")
    public Integer upload(@RequestParam MultipartFile file) throws IOException {
        String originalFilename = file.getOriginalFilename();
        String type = FileUtil.extName(originalFilename);
        long size = file.getSize();

        // 定义一个文件唯一的标识码
        String fileUUID = IdUtil.fastSimpleUUID() + StrUtil.DOT + type;

        File uploadFile = new File(fileUploadPath + fileUUID);
        // 判断配置的文件目录是否存在，若不存在则创建一个新的文件目录
        File parentFile = uploadFile.getParentFile();
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }

        String url;
        // 获取文件的md5
        String md5 = SecureUtil.md5(file.getInputStream());
        // 从数据库查询是否存在相同的记录
        Files dbFiles = getFileByMd5(md5);
        if (dbFiles != null) {
            url = dbFiles.getUrl();
        } else {
            // 上传文件到磁盘
            file.transferTo(uploadFile);
            // 数据库若不存在重复文件，则不删除刚才上传的文件
//            url = "http://" + serverIp + StrUtil.COLON + serverPort +"/shared/files/" + fileUUID;
            url = "/shared/files/" + fileUUID;
        }

        // 存储数据库
        Files saveFile = new Files();
        saveFile.setSize(size / 1024); // 单位 kb
        saveFile.setUrl(url);
        saveFile.setMd5(md5);
        filesMapper.insert(saveFile);

        Integer fileId = saveFile.getId();
        return fileId;
    }

    @ApiOperation(
            value = "根据url获取文件",
            notes = "根据url获取文件，url通过其他接口获取",
            response = void.class,
            tags = {"根据url获取文件"}
    )
    @GetMapping("/{fileUUID}")
    public void download(@PathVariable String fileUUID, HttpServletResponse response) throws IOException {
        // 根据文件的唯一标识码获取文件
        File uploadFile = new File(fileUploadPath + fileUUID);
        // 设置输出流的格式
        ServletOutputStream os = response.getOutputStream();
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileUUID, "UTF-8"));
        response.setContentType("application/octet-stream");

        // 读取文件的字节流
        os.write(FileUtil.readBytes(uploadFile));
        os.flush();
        os.close();
    }

    @ApiOperation(
            value = "根据文件id获取文件url",
            notes = "必须传参：\n" +
                    "fileId (Integer)\n",
            response = Result.class,
            tags = {"根据文件id获取文件url"}
    )
    @GetMapping("/url/{fileId}")
    public Result getFileUrlById(@PathVariable Integer fileId) {
        String url = null;
        if(fileId != null){
            url = filesService.getFileUrlById(fileId);
        }
        if (url == null) {
            url = "http://" + serverIp + StrUtil.COLON + serverPort +"/shared/files/2608b7959c4648f295e077b513c861cd.png";
        }
        return Result.success("http://" + serverIp + StrUtil.COLON + serverPort + url);
    }

    private Files getFileByMd5(String md5) {
        // 查询文件的md5是否存在
        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("md5", md5);
        List<Files> filesList = filesMapper.selectList(queryWrapper);
        return filesList.size() == 0 ? null : filesList.get(0);
    }

}
